package com.ljt.yupictureddd.domain.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ljt.yupictureddd.shared.manager.auth.StpKit;
import com.ljt.yupictureddd.domain.user.constant.UserConstant;
import com.ljt.yupictureddd.domain.user.entity.User;
import com.ljt.yupictureddd.domain.user.repository.UserRepository;
import com.ljt.yupictureddd.domain.user.service.UserDomainService;
import com.ljt.yupictureddd.domain.user.valueobject.UserRoleEnums;
import com.ljt.yupictureddd.infrastracture.exception.BusinessException;
import com.ljt.yupictureddd.infrastracture.exception.ErrorCode;
import com.ljt.yupictureddd.infrastracture.exception.ThrowUtils;
import com.ljt.yupictureddd.interfaces.dto.user.UserQueryRequest;
import com.ljt.yupictureddd.interfaces.dto.user.UserRegisterRequest;
import com.ljt.yupictureddd.interfaces.vo.user.LoginUserVO;
import com.ljt.yupictureddd.interfaces.vo.user.UserVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 六件套
 * @description 针对表【user(用户)】的数据库操作Service实现
 * @createDate 2025-03-05 19:37:54
 */
@Service
@Slf4j
@AllArgsConstructor
public class UserDomainServiceImpl implements UserDomainService {

    private final UserRepository userRepository;

    /**
     * 用户注册
     *
     * @param request
     * @return
     */
    @Override
    public long userRegister(UserRegisterRequest request) {
        String userAccount = request.getUserAccount();
        String userPassword = request.getUserPassword();

//        2.检查用户账户是否和数据库已有的重复
        Long count = userRepository.getBaseMapper().selectCount(new QueryWrapper<User>().eq("userAccount", userAccount));
        ThrowUtils.throwIf(count > 0, ErrorCode.PARAMS_ERROR, "账号重复");
//        3.密码一定要加密
        String encryptedPassword = getEncryptedPassword(userPassword);
//        4.插入数据到数据库中

        User user = new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(encryptedPassword);
        user.setUserName("无名");
        user.setUserRole(UserRoleEnums.USER.getValue());

        boolean save = userRepository.save(user);
        ThrowUtils.throwIf(!save, ErrorCode.SYSTEM_ERROR, "注册失败，数据库错误");
        return user.getId();
    }

    @Override
    public LoginUserVO userLogin(String userAccount, String userPassword, HttpServletRequest request) {
//        2.对用户传递密码加密
        String encryptedPassword = getEncryptedPassword(userPassword);
//        3.查询数据库中用户是否存在
        User user = userRepository.getOne(new QueryWrapper<User>().eq("userAccount", userAccount).eq("userPassword", encryptedPassword));
//        不存在,抛出异常
        if (user == null) {
            log.info("用户登陆失败，账号密码不匹配");
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在 或者用户账号、密码错误");
        }
//        4.记录用户的登陆态
        request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE, user);
        // 别忘了现在在用，sa-token。所以要告诉satoken，要登录了。
        // 注意保证该用户信息与 SpringSession 中的信息过期时间一致（放心没什么事情，还是和session一样的。。）
        StpKit.SPACE.login(user.getId());
        StpKit.SPACE.getSession().set(UserConstant.USER_LOGIN_STATE, user);

        return getLoginUserVO(user);
    }

    /**
     * 获取当前User
     *
     * @param request
     * @return
     */
    @Override
    public User getLoginUser(HttpServletRequest request) {
//        判断是否已经登陆
        Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        User currentUser = (User) userObj;
        ThrowUtils.throwIf(currentUser == null || currentUser.getId() == null, ErrorCode.NOT_LOGIN_ERROR);
//        从数据库查询（追求性能就不用，但是能不用缓存就不用缓存）
        currentUser = userRepository.getById(currentUser.getId());
        ThrowUtils.throwIf(currentUser == null, ErrorCode.NOT_LOGIN_ERROR);
        return currentUser;
    }

    /**
     * 用户退出系统
     *
     * @param request
     * @return
     */
    @Override
    public boolean userLogout(HttpServletRequest request) {
//                判断是否已经登陆
        Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
//        用户已经没有登陆，抛异常
        ThrowUtils.throwIf(userObj == null, ErrorCode.OPERATION_ERROR, "未登录");
//        移除登陆态
        request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE);
        return true;
    }

    @Override
    public QueryWrapper<User> getQueryWrapper(UserQueryRequest request) {
        ThrowUtils.throwIf(request == null,ErrorCode.PARAMS_ERROR,"请求参数为空");

        Long id = request.getId();
        String userAccount = request.getUserAccount();
        String userName = request.getUserName();
        String userProfile = request.getUserProfile();
        String userRole = request.getUserRole();
        String sortField = request.getSortField();
        String sortOrder = request.getSortOrder();

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjUtil.isNotNull(id),"id",id);
        queryWrapper.eq(StrUtil.isNotBlank(userRole),"userRole",userRole);
        queryWrapper.like(StrUtil.isNotBlank(userAccount),"userAccount",userAccount);
        queryWrapper.like(StrUtil.isNotBlank(userName),"userName",userName);
        queryWrapper.like(StrUtil.isNotBlank(userProfile),"userProfile",userProfile);
        queryWrapper.orderBy(StrUtil.isNotEmpty(sortField),sortOrder.equals("ascend"),sortField);

        return queryWrapper;
    }

    /**
     * 获得脱敏的登陆用户VO
     *
     * @param user 数据库查出来的user
     * @return 脱敏的用户VO
     */
    @Override
    public LoginUserVO getLoginUserVO(User user) {
        if (user == null) {
            return null;
        }
        LoginUserVO loginUserVO = BeanUtil.copyProperties(user, LoginUserVO.class);
        return loginUserVO;
    }

    /**
     * 转换用户脱敏后的用户VO
     * @param user
     * @return
     */
    public UserVO getUserVO(User user){
        if (user==null){
            return null;
        }
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        return userVO;
    }

    /**
     * 转换用户脱敏后的用户VO
     * @param user
     * @return
     */
    public List<UserVO> getUserVOList(List<User> user){
        if (CollectionUtils.isEmpty(user)){
            return new ArrayList<>();
        }
        return user.stream()
                .map(this::getUserVO)
                .collect(Collectors.toList());
    }

    /**
     * 密码加密
     *
     * @param userPassword 注册登陆的提交的密码
     * @return 加密后的密码
     */
    public String getEncryptedPassword(String userPassword) {
        final String salt = "ljt";
        return DigestUtils.md5DigestAsHex((salt + userPassword).getBytes());
    }

    @Override
    public boolean save(User user) {
        return userRepository.save(user);
    }

    @Override
    public User getById(long id) {
        return userRepository.getById(id);
    }

    @Override
    public boolean removeById(Long id) {
        return userRepository.removeById(id);
    }

    @Override
    public boolean updateById(User user) {
        return userRepository.updateById(user);
    }

    @Override
    public Page<User> page(Page<User> objectPage, QueryWrapper<User> queryWrapper) {
        return userRepository.page(objectPage,queryWrapper);
    }

    @Override
    public List<User> listByIds(Collection<Long> userIdSet) {
        return userRepository.listByIds(userIdSet);
    }
}




